/*
* Copyright (C) 2020 ~ 2024 chaigec All Rights Reserved.
*
* Author:     chaigec <chaigec@163.com>
* Maintainer: chaigec <chaigec@163.com>

 * Use of this source code is governed by MIT license that can be found in the
 * LICENSE file in the root of the source tree. All contributing project authors
 * may be found in the AUTHORS file in the root of the source tree.
*/

#include "MkFlv/MkFlvDemuxer.h"
#include "MkMedia/MkMediaUtil.h"
#include "MkFlv/MkFlvMuxer.h"
#include "MkEvent/MkTimer.h"
#include "MkMedia/MkFileSource.h"
#include "MkFlv/MkFlvFileSource.h"
#include "MkPs/MkPsMuxer.h"

CMkTimer* g_pTimer = nullptr;
void Flv265DemuxerAndMuxer()
{
    //FILE *fp = fopen("C:/Workspace/media/h265.flv.out1.dat", "rb");
    FILE *fp = fopen("C:/Workspace/media/WTNY.flv.dat", "rb");
    //FILE *fp = fopen("C:/Workspace/media/1.dat", "rb");
    FILE *fpVideo = fopen("C:/Workspace/media/h265.flv.265", "wb");
    FILE *fpAudio = fopen("C:/Workspace/media/flv.aac", "wb");
    FILE *fpOut = fopen("C:/Workspace/media/h265.flv.out.dat", "wb");
    Uint8 pBuf[LenHalfM] = { 0 };
    Uint32 nOffset = 0;
    CMkFlvDemuxer Demuxer;
    BOOL bWriteSei = FALSE;
    BOOL bFirst = TRUE;
    CMkBufferList BufferList;
    Uint8 pMuxerBuf[Len1K] = { 0 };
    while (1) {
        Uint32 NeedRead = LenHalfM - nOffset;
        int nRet = fread(pBuf + nOffset, 1, NeedRead, fp);
        if (nRet <= 0) {
            break;
        }
        nOffset += nRet;
        Uint32 nUsed = 0;
        Demuxer.InputData(pBuf, nOffset, nUsed);

        MkEsPacket EsPacket;
        Uint32 ErrorCode = NoneError;
        Uint32 nTmpUsed = 0;
        MkListBuffer::const_iterator it;
        while (1) {
            ErrorCode = Demuxer.GetEsPacket(EsPacket);
            printf("es pts:%d\n", EsPacket.Pts);
            if (NoneError != ErrorCode) {
                break;
            }
            if (bFirst) {
                BufferList.Clear();
                CMkFlvMuxer::PacketHeader(Demuxer.GetVideoParam(), Demuxer.GetAudioParam(), Demuxer.GetFileSize(), Demuxer.GetDuration(), pMuxerBuf, Len1K, BufferList);
                it = BufferList.GetBufferList().begin();
                for (; it != BufferList.GetBufferList().end(); it++) {
                    fwrite(it->GetBuffer(), 1, it->GetLength(), fpOut);
                }
            }
            BufferList.Clear();
            CMkFlvMuxer::PacketEsPacket(Demuxer.GetVideoParam(), Demuxer.GetAudioParam(), EsPacket, pMuxerBuf, Len1K, nTmpUsed, BufferList);
            it = BufferList.GetBufferList().begin();
            for (; it != BufferList.GetBufferList().end(); it++) {
                fwrite(it->GetBuffer(), 1, it->GetLength(), fpOut);
            }
            bFirst = FALSE;

            if (MkCodecH265 == EsPacket.CodecType) {
                it = EsPacket.BufferList.GetBufferList().begin();
                for (; it != EsPacket.BufferList.GetBufferList().end(); it++) {
                    fwrite(&NaluStartCode, 1, 4, fpVideo);
                    fwrite(it->GetBuffer(), 1, it->GetLength(), fpVideo);
                }
            } else if (MkCodecAac == EsPacket.CodecType) {
                Uint8 pAdts[Len16] = { 0 };
                CMkMediaUtil::CreateAacAdts(Demuxer.GetAudioParam().GetObjectType(), Demuxer.GetAudioParam().GetSampleRate(), Demuxer.GetAudioParam().GetChannel(), EsPacket.BufferList.GetTatolLen(), pAdts);
                Uint32 nLen = 0;
                CMkAudioParam AudioParam = Demuxer.GetAudioParam();
                MkAacObjectType ObjectType;
                MkAudioSampleRate SampleRate;
                Uint8 nChannel;
                CMkMediaUtil::AacAdtsParse(pAdts,Len16, ObjectType, SampleRate, nChannel);
                fwrite(pAdts, 1, MkAacAdtsLen, fpAudio);
                //fwrite(EsPacket.pData, 1, EsPacket.nSize, fpAudio);
                it = EsPacket.BufferList.GetBufferList().begin();
                for (; it != EsPacket.BufferList.GetBufferList().end(); it++) {
                    fwrite(&NaluStartCode, 1, 4, fpVideo);
                    fwrite(it->GetBuffer(), 1, it->GetLength(), fpVideo);
                }
            }
        }

        memmove(pBuf, pBuf + nUsed, nOffset - nUsed);
        nOffset -= nUsed;
    }
    fclose(fp);
    fclose(fpAudio);
    fclose(fpVideo);
    fclose(fpOut);
}

void Flv264DemuxerAndMuxer()
{
    FILE *fp = fopen("C:/Workspace/media/WTNY.dat", "rb");
    FILE *fpVideo = fopen("C:/Workspace/media/flv.h264", "wb");
    FILE *fpAudio = fopen("C:/Workspace/media/flv.aac", "wb");

    CMkFlvFileSource *pFlvSource = new CMkFlvFileSource(fp, g_pTimer);
    pFlvSource->StartMediaSource([](CMkMediaSource* pMediaSource, Uint32 ErrorCode) {
        printf("start flv file source failed\n");
        return NoneError;
    }, [fpVideo, fpAudio](const MkEsPacket& EsPacket, const CMkVideoParam& VideoParam, const CMkAudioParam& AudioParam) {
        if (EsPacket.BufferList.Empty()) {
            g_pTimer->LoopBreak();
            fclose(fpAudio);
            fclose(fpAudio);
        } else {
            FILE *fpw = EsPacket.CodecType > MkCodecCavs ? fpAudio : fpVideo;
            MkListBuffer::const_iterator it = EsPacket.BufferList.GetBufferList().begin();
            for (; it != EsPacket.BufferList.GetBufferList().end(); it++) {
                if (MkCodecAac == EsPacket.CodecType) {
                    Uint8 pAdts[MkAacAdtsLen] = { 0 };
                    CMkMediaUtil::CreateAacAdts(AudioParam.GetObjectType(), AudioParam.GetSampleRate(), AudioParam.GetChannel(), it->GetLength(), pAdts);
                    fwrite(pAdts, 1, MkAacAdtsLen, fpAudio);
                    fwrite(it->GetBuffer(), 1, it->GetLength(), fpAudio);
                } else if (MkCodecH264 == EsPacket.CodecType || MkCodecH265 == EsPacket.CodecType) {
                    fwrite(&NaluStartCode, 1, 4, fpVideo);
                    fwrite(it->GetBuffer(), 1, it->GetLength(), fpVideo);
                }
            }
        }
        return NoneError;
    });

    //FILE *fpOut = fopen("C:/Workspace/media/out.dat", "wb");
    //Uint8 pBuf[LenHalfM] = { 0 };
    //Uint32 nOffset = 0;
    //CMkFlvDemuxer Demuxer;
    //BOOL bWriteSei = FALSE;
    //BOOL bFirst = TRUE;
    //CMkBufferList BufferList;
    //Uint8 pMuxerBuf[Len1K] = { 0 };
    //CMkAudioParam AudioParam;
    //while (1) {
    //    Uint32 NeedRead = LenHalfM - nOffset;
    //    int nRet = fread(pBuf + nOffset, 1, NeedRead, fp);
    //    if (nRet <= 0) {
    //        break;
    //    }
    //    nOffset += nRet;
    //    Uint32 nUsed = 0;
    //    Demuxer.InputData(pBuf, nOffset, nUsed);

    //    MkEsPacket EsPacket;
    //    Uint32 ErrorCode = NoneError;
    //    Uint32 nTmpUsed = 0;
    //    MkListBuffer::const_iterator it;
    //    while (1) {
    //        ErrorCode = Demuxer.GetEsPacket(EsPacket);
    //        if (NoneError != ErrorCode) {
    //            break;
    //        }
    //        if (bFirst) {
    //            BufferList.Clear();
    //            CMkFlvMuxer::PacketHeader(Demuxer.GetVideoParam(), AudioParam/*Demuxer.GetAudioParam()*/, Demuxer.GetFileSize(), Demuxer.GetDuration(), pMuxerBuf, Len1K, BufferList);
    //            it = BufferList.GetBufferList().begin();
    //            for (; it != BufferList.GetBufferList().end(); it++) {
    //                fwrite(it->GetBuffer(), 1, it->GetLength(), fpOut);
    //            }
    //        }
    //        if (EsPacket.CodecType < MkCodecCavs) {
    //            BufferList.Clear();
    //            CMkFlvMuxer::PacketEsPacket(Demuxer.GetVideoParam(), AudioParam/*Demuxer.GetAudioParam()*/, EsPacket, pMuxerBuf, Len1K, nTmpUsed, BufferList);
    //            it = BufferList.GetBufferList().begin();
    //            for (; it != BufferList.GetBufferList().end(); it++) {
    //                fwrite(it->GetBuffer(), 1, it->GetLength(), fpOut);
    //            }
    //        }
    //        bFirst = FALSE;

    //        BOOL bWriteSps = FALSE;
    //        if (MkCodecH264 == EsPacket.CodecType) {
    //            it = EsPacket.BufferList.GetBufferList().begin();
    //            for (; it != EsPacket.BufferList.GetBufferList().end(); it++) {
    //                if (!bWriteSps) {
    //                    Uint8 NaluType = 0;
    //                    CMkMediaUtil::Get264NaluType(*(Uint8*)it->GetBuffer(), NaluType);
    //                    if (MkH264NalSlice != NaluType) {
    //                        fwrite(&NaluStartCode, 1, 4, fpVideo);
    //                        fwrite(Demuxer.GetVideoParam().GetSps().c_str(), 1, Demuxer.GetVideoParam().GetSps().size(), fpVideo);
    //                        fwrite(&NaluStartCode, 1, 4, fpVideo);
    //                        fwrite(Demuxer.GetVideoParam().GetPps().c_str(), 1, Demuxer.GetVideoParam().GetPps().size(), fpVideo);
    //                    }
    //                    bWriteSps = TRUE;
    //                }
    //                fwrite(&NaluStartCode, 1, 4, fpVideo);
    //                fwrite(it->GetBuffer(), 1, it->GetLength(), fpVideo);
    //            }
    //        } else if (MkCodecAac == EsPacket.CodecType) {
    //            //const CMkAacParam* pAacParam = dynamic_cast<const CMkAacParam*>(Demuxer.GetAudioParam());
    //            //if (pAacParam) {
    //            //    MkString AacAdts;
    //            //    pAacParam->CreateAacAdts(EsPacket.nSize, AacAdts);
    //            //    Uint32 nLen = 0;
    //            //    CMkAacParam param = *pAacParam;
    //            //    param.AacAdtsParse((const Uint8*)AacAdts.c_str(), 7, nLen);
    //            //    it = EsPacket.BufferList.GetBufferList().begin();
    //            //    for (; it != EsPacket.BufferList.GetBufferList().end()) {
    //            //        fwrite(&NaluStartCode, 1, 4, fpVideo);
    //            //        fwrite((*it)->GetBuffer(), 1, (*it)->GetLength(), fpVideo);
    //            //    }
    //            //    fwrite(AacAdts.c_str(), 1, AacAdts.size(), fpAudio);
    //            //    fwrite(EsPacket.pData, 1, EsPacket.nSize, fpAudio);
    //            //}
    //        }
    //    }

    //    memmove(pBuf, pBuf + nUsed, nOffset - nUsed);
    //    nOffset -= nUsed;
    //}
    //fclose(fp);
    //fclose(fpAudio);
    //fclose(fpVideo);
    //fclose(fpOut);
}

BOOL bFirstPacket = TRUE;
CMkBufferList BufferList;
MkListBuffer::const_iterator it;
Uint8 pBuf[Len1K] = { 0 };
void H264MuxerAndDeMuxer()
{
    //FILE *fp264 = fopen("C:/Workspace/media/aa.h264", "rb");
    FILE *fp264 = fopen("C:/Workspace/media/flvaa.h264", "rb");
    FILE *fpOut = fopen("C:/Workspace/media/aa.flv.dat", "wb");
    CMkTimer Timer;
    CMkTimer* pTimer = &Timer;

    CMkH264FileSource FileSource(fp264, &Timer);
    FileSource.StartMediaSource([](CMkMediaSource* pMediaSource, Uint32 ErrorCode) {
        return NoneError;
    }, [fpOut, pTimer](const MkEsPacket& EsPacket, const CMkVideoParam& VideoParam, const CMkAudioParam& AudioParam) {
        Uint32 nTmpUsed = 0;
        if (bFirstPacket) {
            BufferList.Clear();
            CMkFlvMuxer::PacketHeader(VideoParam, AudioParam, 0, 0, pBuf, Len1K, BufferList);
            it = BufferList.GetBufferList().begin();
            for (; it != BufferList.GetBufferList().end(); it++) {
                fwrite(it->GetBuffer(), 1, it->GetLength(), fpOut);
            }
        }
        BufferList.Clear();
        CMkFlvMuxer::PacketEsPacket(VideoParam, AudioParam, EsPacket, pBuf, Len1K, nTmpUsed, BufferList);
        it = BufferList.GetBufferList().begin();
        for (; it != BufferList.GetBufferList().end(); it++) {
            fwrite(it->GetBuffer(), 1, it->GetLength(), fpOut);
        }
        bFirstPacket = FALSE;
        if (EsPacket.BufferList.Empty()) {
            fclose(fpOut);
            pTimer->LoopBreak();
        }
        return NoneError;
    });
    Timer.Dispatch();
}

void H265MuxerAndDeMuxer()
{
    //FILE *fp264 = fopen("C:/Workspace/media/aa.h264", "rb");
 /*   FILE *fp265 = fopen("C:/Workspace/media/aa.265", "rb");
    FILE *fpOut = fopen("C:/Workspace/media/h265.flv.outfile.dat", "wb");

    CMkH265FileSource FileSource(fp265, g_pTimer, [fpOut](const MkEsPacket& EsPacket, const CMkVideoParam& VideoParam, const CMkAudioParam& AudioParam) {
        Uint32 nTmpUsed = 0;
        CMkH265FileSource *pH264Source = dynamic_cast<CMkH265FileSource*>(pMediaSource);
        if (bFirstPacket) {
            BufferList.Clear();
            CMkFlvMuxer::PacketHeader(pMediaSource->GetVideoParam(), pMediaSource->GetAudioParam(), pH264Source->m_FileSize, pH264Source->m_Duration, pBuf, Len1K, BufferList);
            it = BufferList.GetBufferList().begin();
            for (; it != BufferList.GetBufferList().end(); it++) {
                fwrite(it->GetBuffer(), 1, it->GetLength(), fpOut);
            }
        }
        BufferList.Clear();
        CMkFlvMuxer::PacketEsPacket(pMediaSource->GetVideoParam(), pMediaSource->GetAudioParam(), EsPacket, pBuf, Len1K, nTmpUsed, BufferList);
        it = BufferList.GetBufferList().begin();
        for (; it != BufferList.GetBufferList().end(); it++) {
            fwrite(it->GetBuffer(), 1, it->GetLength(), fpOut);
        }
        bFirstPacket = FALSE;
        if (EsPacket.BufferList.Empty()) {
            fclose(fpOut);
            g_pTimer->LoopBreak();
        }
    }, [](CMkMediaSource* pMediaSource, Uint32 ErrorCode) {

    });
    FileSource.Start();
    g_pTimer->Dispatch();*/
}

void test()
{
    //FILE *fp264 = fopen("E:/opensource/mksource/ut/source/1.264", "rb");
    //FILE *fpOut = fopen("E:/opensource/mksource/ut/source/2.264", "wb");
    //CMkTimer Timer;
    //CMkTimer* pTimer = &Timer;
    //CMkH264FileSource FileSource(fp264, &Timer, [fpOut, pTimer](const MkEsPacket& EsPacket, const CMkVideoParam& VideoParam, const CMkAudioParam& AudioParam) {
    //    MkListBuffer::const_iterator it = EsPacket.BufferList.GetBufferList().begin();
    //    for (int i = 0; it != EsPacket.BufferList.GetBufferList().end(); it++, i++) {
    //        MkString FileName = "E:/opensource/mksource/ut/source/" + std::to_string(i) + ".dat";
    //        FILE *fp = fopen(FileName.c_str(), "wb");
    //        fwrite(&NaluStartCode, 1, 4, fp);
    //        fwrite(it->GetBuffer(), 1, it->GetLength(), fp);
    //        fclose(fp);
    //    }
    //    if (EsPacket.BufferList.Empty()) {
    //        pTimer->LoopBreak();
    //    }
    //}, [fpOut](CMkMediaSource* pMediaSource, Uint32 ErrorCode) {
    //    //
    //});
    //FileSource.ScanFile();
    //FileSource.Start();
    //Timer.Dispatch();
    //fclose(fp264);
    //fclose(fpOut);
}

void test2()
{
    FILE *fp265 = fopen("C:/Workspace/media/tmp1.265", "rb");
    
    CMkTimer Timer;
    CMkTimer* pTimer = &Timer;
    CMkH265FileSource FileSource(fp265, &Timer);
    FileSource.StartMediaSource([](CMkMediaSource* pMediaSource, Uint32 ErrorCode) {
        return NoneError;
    }, [pTimer](const MkEsPacket& EsPacket, const CMkVideoParam& VideoParam, const CMkAudioParam& AudioParam) {
        if (EsPacket.bKeyPacket)
        {
            FILE *fpOut = fopen("C:/Workspace/media/tmp2.265", "wb");
            MkListBuffer::const_iterator it = EsPacket.BufferList.GetBufferList().begin();
            for (int i = 0; it != EsPacket.BufferList.GetBufferList().end(); it++, i++) {
                fwrite(&NaluStartCode, 1, 4, fpOut);
                fwrite(it->GetBuffer(), 1, it->GetLength(), fpOut);
            }
            fclose(fpOut);
        }
        static int i = 0;
        printf("frame index:%d key frame:%d\n", i++, EsPacket.bKeyPacket);
        if (i==246)
        {
            printf("11\n");
        }
        if (EsPacket.BufferList.Empty()) {
            pTimer->LoopBreak();
        }
        return NoneError;
    });
    Timer.Dispatch();
    fclose(fp265);
}


void AacToFlv()
{
    /*FILE *fpAac = fopen("C:/Workspace/media/WTNY.aac.dat", "rb");
    FILE *fpOut = fopen("C:/Workspace/media/WTNY.out.Aac.flv.dat", "wb");

    CMkTimer Timer;
    g_pTimer = &Timer;
    CMkAacFileSource *pAacFileSource = new CMkAacFileSource(fpAac, g_pTimer, [fpOut](const MkEsPacket& EsPacket, const CMkVideoParam& VideoParam, const CMkAudioParam& AudioParam) {
        if (EsPacket.BufferList.Empty()) {
            g_pTimer->LoopBreak();
            return;
        }
        CMkAacFileSource *pAacFileSource = dynamic_cast<CMkAacFileSource*>(pMediaSource);
        if (bFirstPacket) {
            BufferList.Clear();
            CMkFlvMuxer::PacketHeader(pMediaSource->GetVideoParam(), pMediaSource->GetAudioParam(), pAacFileSource->m_FileSize, pAacFileSource->m_Duration, pBuf, Len1K, BufferList);
            it = BufferList.GetBufferList().begin();
            for (; it != BufferList.GetBufferList().end(); it++) {
                fwrite(it->GetBuffer(), 1, it->GetLength(), fpOut);
            }
        }
        BufferList.Clear();
        Uint32 nTmpUsed = 0;
        CMkFlvMuxer::PacketEsPacket(pMediaSource->GetVideoParam(), pMediaSource->GetAudioParam(), EsPacket, pBuf, Len1K, nTmpUsed, BufferList);
        it = BufferList.GetBufferList().begin();
        for (; it != BufferList.GetBufferList().end(); it++) {
            fwrite(it->GetBuffer(), 1, it->GetLength(), fpOut);
        }
        bFirstPacket = FALSE;
    }, [](CMkMediaSource* pMediaSource, Uint32 ErrorCode) {
        printf("get aac file source success\n");
    });
    pAacFileSource->ScanFile();
    pAacFileSource->Start();
    Timer.Dispatch();
    fclose(fpOut);
    fclose(fpAac);*/
}


void FlvDemuxer(const MkString& FlvFile, const MkString& AudioFile, const MkString& VideoFile)
{
    //FILE *fp = fopen(FlvFile.c_str(), "rb");
    //FILE *fpVideo = fopen(VideoFile.c_str(), "wb");
    //FILE *fpAudio = fopen(AudioFile.c_str(), "wb");

    //CMkFlvFileSource *pFlvSource = new CMkFlvFileSource(fp, g_pTimer, [fpVideo, fpAudio](const MkEsPacket& EsPacket, const CMkVideoParam& VideoParam, const CMkAudioParam& AudioParam) {
    //    if (EsPacket.BufferList.Empty()) {
    //        g_pTimer->LoopBreak();
    //        fclose(fpAudio);
    //        fclose(fpAudio);
    //        pMediaSource->Stop();
    //    } else {
    //        //if ((MkCodecH264 == EsPacket.CodecType || MkCodecH265 == EsPacket.CodecType)
    //        //    && EsPacket.bKeyPacket
    //        //    && BufferList.GetBufferList().size() < 3) {
    //        //    if (!pMediaSource->GetVideoParam().GetVps().empty()) {
    //        //        fwrite(&NaluStartCode, 1, 4, fpVideo);
    //        //        fwrite(pMediaSource->GetVideoParam().GetVps().c_str(), 1, pMediaSource->GetVideoParam().GetVps().size(), fpVideo);
    //        //    }
    //        //    if (!pMediaSource->GetVideoParam().GetSps().empty()) {
    //        //        fwrite(&NaluStartCode, 1, 4, fpVideo);
    //        //        fwrite(pMediaSource->GetVideoParam().GetSps().c_str(), 1, pMediaSource->GetVideoParam().GetSps().size(), fpVideo);
    //        //    }
    //        //    if (!pMediaSource->GetVideoParam().GetPps().empty()) {
    //        //        fwrite(&NaluStartCode, 1, 4, fpVideo);
    //        //        fwrite(pMediaSource->GetVideoParam().GetPps().c_str(), 1, pMediaSource->GetVideoParam().GetPps().size(), fpVideo);
    //        //    }
    //        //}
    //        MkListBuffer::const_iterator it = EsPacket.BufferList.GetBufferList().begin();
    //        for (; it != EsPacket.BufferList.GetBufferList().end(); it++) {
    //            if (MkCodecAac == EsPacket.CodecType) {
    //                Uint8 pAdts[MkAacAdtsLen] = { 0 };
    //                CMkMediaUtil::CreateAacAdts(pMediaSource->GetAudioParam().GetObjectType(), pMediaSource->GetAudioParam().GetSampleRate(), pMediaSource->GetAudioParam().GetChannel(), it->GetLength(), pAdts);
    //                fwrite(pAdts, 1, MkAacAdtsLen, fpAudio);
    //                fwrite(it->GetBuffer(), 1, it->GetLength(), fpAudio);
    //            } else if (MkCodecH264 == EsPacket.CodecType || MkCodecH265 == EsPacket.CodecType) {
    //                fwrite(&NaluStartCode, 1, 4, fpVideo);
    //                fwrite(it->GetBuffer(), 1, it->GetLength(), fpVideo);
    //            }
    //        }
    //    }
    //}, [](CMkMediaSource* pMediaSource, Uint32 ErrorCode) {
    //    printf("start flv file source failed\n");
    //});
    //pFlvSource->ScanFile();
    //pFlvSource->Start();
}

int FlvToPs(const MkString& FlvFile, const MkString& PsFile)
{
    FILE *fp = fopen(FlvFile.c_str(), "rb");
    FILE *fpPs = fopen(PsFile.c_str(), "wb");

    CMkFlvFileSource *pFlvSource = new CMkFlvFileSource(fp, g_pTimer);/*, [fpPs](const MkEsPacket& EsPacket, const CMkVideoParam& VideoParam, const CMkAudioParam& AudioParam) {
        if (EsPacket.BufferList.Empty()) {
            g_pTimer->LoopBreak();
            fclose(fpPs);
            pMediaSource->Stop();
        } else {
            CMkBufferList BufferList;
            g_psMuxer->AddPacket(EsPacket, BufferList);
            MkListBuffer::const_iterator it = BufferList.GetBufferList().begin();
            for (; it != BufferList.GetBufferList().end(); it++) {
                fwrite(it->GetBuffer(), 1, it->GetLength(), fpPs);
            }
        }
    }, [](CMkMediaSource* pMediaSource, Uint32 ErrorCode) {
        printf("start flv file source failed\n");
        g_psMuxer = new CMkPsMuxer(pMediaSource->GetVideoParam(), pMediaSource->GetAudioParam());
    });*/
    pFlvSource->StartMediaSource([](CMkMediaSource* pSource, Uint32 ErrorCode) {
        printf("start flv file source failed\n");
        //g_psMuxer = new CMkPsMuxer(pSource->GetVideoParam(), pSource->GetAudioParam());
        return NoneError;
    }, [fpPs](const MkEsPacket& EsPacket, const CMkVideoParam& VideoParam, const CMkAudioParam& AudioParam) {
        if (EsPacket.BufferList.Empty()) {
            g_pTimer->LoopBreak();
            fclose(fpPs);
        } else {
            if (MkCodecH264 == EsPacket.CodecType && EsPacket.bKeyPacket)
            {
                FILE* fp = fopen("a.264", "wb");
                MkListBuffer::const_iterator itt = EsPacket.BufferList.GetBufferList().begin();
                for (; itt != EsPacket.BufferList.GetBufferList().end(); itt++) {
                    fwrite(&NaluStartCode, 1, 4, fp);
                    fwrite(itt->GetBuffer(), 1, itt->GetLength(), fp);
                }
                fclose(fp);
            } else if(MkCodecAac == EsPacket.CodecType) {
                FILE* fp = fopen("a.aac", "wb");
                MkListBuffer::const_iterator itt = EsPacket.BufferList.GetBufferList().begin();
                for (; itt != EsPacket.BufferList.GetBufferList().end(); itt++) {
                    Uint8 pBuf[Len16] = { 0 };
                    CMkMediaUtil::CreateAacAdts(AudioParam.GetObjectType(), AudioParam.GetSampleRate(), AudioParam.GetChannel(), itt->GetLength(), pBuf);
                    fwrite(pBuf, 1, MkAacAdtsLen, fp);
                    fwrite(itt->GetBuffer(), 1, itt->GetLength(), fp);
                }
                fclose(fp);
            }

            CMkBufferList BufferList;
            Uint8 pBuf[Len20K] = { 0 };
            Uint32 nUsed = 0;
            CMkPsMuxer::PacketEsPacket(VideoParam, AudioParam, EsPacket, pBuf, Len20K, nUsed, BufferList);
            MkListBuffer::const_iterator it = BufferList.GetBufferList().begin();
            for (; it != BufferList.GetBufferList().end(); it++) {
                fwrite(it->GetBuffer(), 1, it->GetLength(), fpPs);
            }
        }
        return NoneError;
    });
    return NoneError;
}

int main(int argc, char ** argv)
{
    //AacToFlv();
    //return 1;
    test2();
    return 0;
    CMkTimer Timer;
    g_pTimer = &Timer;
    MkString FlvFile = "C:/Workspace/media/WTNY.flv.dat";
    MkString AudioFile = "C:/Workspace/media/WTNY.out.flv.aac.dat";
    MkString VideoFile = "C:/Workspace/media/WTNY.out.flv.h264.dat";
    MkString PsFile = "C:/Workspace/media/WTNY.out.ps.dat";
    //FlvDemuxer(FlvFile, AudioFile, VideoFile);
    FlvToPs(FlvFile, PsFile);
    Timer.Dispatch();
    return 0;
}
